package com.fingard.dsp.bank.directbank.cib01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.InterBankPayChannel;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import org.springframework.stereotype.Component;

import java.util.Date;
@Component("CIB01SinglePay")
public class CIB01SinglePay extends CIB01Base implements ISinglePay {

    /**
     * 单笔支付，不需采用流处理方式
     * @param p_req1908
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        // 返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail tmpRetDetail;
        tmpRetDetail = d_190802(p_req1908);
        if (tmpRetDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)) {
            tmpRetDetail.reqSeqID = p_req1908.singleDetail.askNumber;
        }
        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    /**
     * 3.4.1 转账汇款指令提交
     */
    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        RetAtsSingleBat retAts = new RetAtsSingleBat(p_req1908BAT);

        try {
            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.autoFormat = false;
            writeCommonHeaderEn(xmlWriter, "encoding=\"gb2312\"");
            xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
            while (p_req1908BAT.readRecord()) {
                ReqPayRecDetail tmpDetail = p_req1908BAT.readedDetail;
                xmlWriter.writeStartElement("XFERTRNRQ");
                xmlWriter.writeElementString("TRNUID", tmpDetail.askNumber);

                xmlWriter.writeStartElement("XFERRQ");


                XElement tmpXElement = new XElement("XFERINFO", "");

                XElement payXElement = new XElement("ACCTFROM", "");// 付款人信息
                payXElement.addChild(new XElement("ACCTID", tmpDetail.payAct));
                payXElement.addChild(new XElement("NAME", tmpDetail.payName));
                payXElement.addChild(new XElement("BANKDESC", tmpDetail.payBankName));
                payXElement.addChild(new XElement("CITY", tmpDetail.getOppProvinceAndCity2()[0]));
                tmpXElement.addChild(payXElement);

                String INTERBANK = (tmpDetail.sameBnk.equals("1") ? ("Y") : ("N"));
                String LOCAL = (tmpDetail.sameCity.equals("1") ? ("Y") : ("N"));
                XElement recXElement = new XElement("ACCTTO#INTERBANK=\"" + INTERBANK + "\"#LOCAL=\"" + LOCAL + "\"", "");// 收款人信息
                recXElement.addChild(new XElement("ACCTID", tmpDetail.recAct));
                recXElement.addChild(new XElement("NAME", tmpDetail.recName));
                recXElement.addChild(new XElement("BANKDESC", tmpDetail.recBankName));
                recXElement.addChild(new XElement("BANKNUM", tmpDetail.cnapsCode));
                recXElement.addChild(new XElement("CITY", tmpDetail.getOppProvinceAndCity2()[0]));
                recXElement.addChild(new XElement("COLLECT", tmpDetail.getOppProvinceAndCity2()[1]));
                tmpXElement.addChild(recXElement);

                tmpXElement.addChild(new XElement("CHEQUENUM", tmpDetail.askNumber));
                tmpXElement.addChild(new XElement("CURSYM", "RMB"));
                tmpXElement.addChild(new XElement("TRNAMT", tmpDetail.payAmount));
                String PMTMODE = (tmpDetail.paySpd.equals("1") ? ("REAL_TIME") : ("URGENT")); // 加急标记
                tmpXElement.addChild(new XElement("PMTMODE", PMTMODE));
                tmpXElement.addChild(new XElement("PURPOSE", tmpDetail.abstractATS));

                String memo = tmpDetail.purpose;
                if (StringHelper.isNullOrEmpty(memo)) {
                    memo = tmpDetail.memo;
                }
                tmpXElement.addChild(new XElement("MEMO", memo));

                nodeAnalysis(tmpDetail.srcXElement, tmpXElement, getCharset());

                xmlWriter.writeXElement(tmpXElement);
                xmlWriter.writeEndElement();
                xmlWriter.writeEndElement();
            }

            xmlWriter.writeEndDocument();

            //WriteBankLogStep2(xmlWriter.toXmlString());

            String xmlSend = writeContentLength(xmlWriter);
            String[] tmpStrRet = sendToBank(xmlSend);

            //WriteBankLogStep3(tmpStrRet[1]);

            if (tmpStrRet[0].length() == 0) {
                String returnXml = tmpStrRet[1].substring(tmpStrRet[1].indexOf("<FOX>"), tmpStrRet[1].length());

                //WriteBankLogLn2("银行响应有效数据:\r\n" + returnXml);

                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(returnXml, tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/CODE");
                    if ("0".equals(tmpRetCode)) {
                        retAts.batRespCode = "0";
                        retAts.batTransState = tmpRetCode;
                        retAts.batPayInfoCode = tmpRetCode;
                        retAts.batRespInfo = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY");

                        while (tmpBkReader.read("/FOX/SECURITIES_MSGSRSV1/XFERTRNRS")) {
                            RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
                            XElement tmpRetNode = tmpBkReader.readedXElement;

                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.respInfo = tmpRetNode.getSingleText("XFERRS/XFERPRCSTS/MESSAGE");
                            tmpRetDetail.reqSeqID = tmpRetNode.getSingleText("TRNUID");
                            tmpRetDetail.transState = tmpRetNode.getSingleText("XFERRS/XFERPRCSTS/XFERPRCCODE");
                            tmpRetDetail.payInfoCode = tmpRetNode.getSingleText("XFERRS/XFERPRCSTS/XFERPRCCODE");

                            retAts.writeRetDetail(tmpRetDetail);
                        }
                    } else {
                        retAts.batRespCode = "-1";
                        retAts.batRespInfo = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY");
                    }
                } else {
                    retAts.batRespCode = "-1";
                    retAts.batRespInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                retAts.batRespCode = "0";
                retAts.batRespInfo = tmpStrRet[1];
                retAts.reqBatchNO = p_req1908BAT.reqBatchNO;
                retAts.batTransState = PaymentState.FAIL_Payment;
                retAts.batPayInfoCode = tmpStrRet[0];
            } else {
                retAts.batRespCode = "-1";
                retAts.batRespInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            retAts.batRespCode = "-1";
            retAts.batRespInfo = ex.getMessage();

            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }

    // 190802对外支付
    private RetAtsSglDetail d_190802(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail();

        Date tmpDateNow = new Date();
        XmlTextWriter xmlWriter = new XmlTextWriter();// 发银行报文的XML对象
        xmlWriter.autoFormat = false;// 报文串需要整个字符串传送，中间需无回车符，否则会签名出错
        writeCommonHeaderEn(xmlWriter, "encoding=\"gb2312\"");
        xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
        xmlWriter.writeStartElement(CIB01TransType.P190802);
        xmlWriter.writeElementString("TRNUID", p_req1908.singleDetail.askNumber);
        xmlWriter.writeStartElement("XFERRQ");
        XElement tmpXElement = new XElement("XFERINFO", "");

        XElement payXElement = new XElement("ACCTFROM", "");
        payXElement.addChild(new XElement("ACCTID", p_req1908.singleDetail.payAct));
        if (!p_req1908.singleDetail.sameBnk.equals("1")) {
            payXElement.addChild(new XElement("NAME", p_req1908.singleDetail.payName));
        }
        tmpXElement.addChild(payXElement);

        String INTERBANK = (p_req1908.singleDetail.sameBnk.equals("1") ? ("Y") : ("N"));
        String LOCAL = (p_req1908.singleDetail.sameCity.equals("1") ? ("Y") : ("N"));
        XElement recXElement = new XElement("ACCTTO", "");//#INTERBANK=\"" + INTERBANK + "\"#LOCAL=\"" + LOCAL + "\"
        recXElement.addAttr("INTERBANK", INTERBANK);
        recXElement.addAttr("LOCAL", LOCAL);
        //recXElement.
        recXElement.addChild(new XElement("ACCTID", p_req1908.singleDetail.recAct));
        recXElement.addChild(new XElement("NAME", p_req1908.singleDetail.recName));
        recXElement.addChild(new XElement("BANKDESC", p_req1908.singleDetail.getOppBankLocation()));
        recXElement.addChild(new XElement("BANKNUM", p_req1908.singleDetail.cnapsCode));
        recXElement.addChild(new XElement("CITY", p_req1908.singleDetail.recAreaName));
        tmpXElement.addChild(recXElement);

        tmpXElement.addChild(new XElement("CHEQUENUM", ""));
        tmpXElement.addChild(new XElement("TRNAMT", p_req1908.singleDetail.payAmount));
        String PMTMODE = (p_req1908.singleDetail.paySpd.equals("1") ? ("REAL_TIME") : ("URGENT")); // 加急标记
        tmpXElement.addChild(new XElement("PMTMODE", PMTMODE));

        String purpose = p_req1908.singleDetail.purpose;
        purpose = purpose + "+" + p_req1908.singleDetail.abstractATS;
        if (null != purpose) {
            tmpXElement.addChild(new XElement("PURPOSE", purpose));
        } else {
            tmpXElement.addChild(new XElement("PURPOSE", p_req1908.singleDetail.description));
        }

        tmpXElement.addChild(new XElement("DTDUE", Format.Date10Format.format(tmpDateNow)));
        tmpXElement.addChild(new XElement("MEMO", p_req1908.singleDetail.memo));

        //校验是否采用网银互联付方式
        InterBankPayChannel bnkPayChan = getInterBankPayChannel(p_req1908.singleDetail);
        if(bnkPayChan.isEBank){
            tmpXElement.setSingleText("PMTMODE","SUPER");
            tmpXElement.getSingleChild("ACCTTO").setSingleText("BANKNUM", bnkPayChan.eBankCode);//收款行行号
            tmpXElement.getSingleChild("ACCTTO").setSingleText("BANKDESC", bnkPayChan.eBankName);//收款行
        }

        nodeAnalysis(p_req1908.singleDetail.srcXElement, tmpXElement, getCharset());
        xmlWriter.writeXElement(tmpXElement);

        xmlWriter.writeEndDocument();// 写入报文完成
        String xmlSend = writeContentLength(xmlWriter);
        String[] tmpStrRet = sendToBank(xmlSend);// 发送银行

        if (tmpStrRet[0].length() == 0) {
            String returnXml = tmpStrRet[1].substring(tmpStrRet[1].indexOf("<FOX>"), tmpStrRet[1].length());
            StringBuilder tmpSbMsg = new StringBuilder();
            // 解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(returnXml, tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader
                        .getFirstText("/FOX/SECURITIES_MSGSRSV1/XFERTRNRS/STATUS/CODE");
                String errorCode = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/XFERTRNRS/STATUS/CODE");
                if (tmpRetCode != null && tmpRetCode.equals("0")) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = "success";
                    retDetail.transState = tmpRetCode;
                    retDetail.payInfoCode = tmpRetCode;
                    retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                } else if (errorCode != null) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/XFERTRNRS/STATUS/MESSAGE");
                    retDetail.payInfoCode = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY") + "+" + errorCode;
                    retDetail.transState = retDetail.payInfoCode;
                    if ("INFO+2000".equals(retDetail.transState)) {
                        retDetail.transState = retDetail.transState + "+" + retDetail.respInfo;
                        retDetail.payInfoCode = retDetail.transState;
                    }
                    retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    /**
     * 状态查询
     * @param p_req1944
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        // 返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);

        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();

        XmlTextWriter xmlWriter = new XmlTextWriter();// 发银行报文的XML对象
        xmlWriter.autoFormat = false;
        writeCommonQryHeaderEn(xmlWriter, "encoding=\"gb2312\"");
        xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
        xmlWriter.writeStartElement(CIB01TransType.Q1908);
        xmlWriter.writeElementString("TRNUID", p_req1944.askNumber);
        xmlWriter.writeStartElement("XFERINQRQ");
        xmlWriter.writeElementString("CLIENTREF", p_req1944.askNumber);
        xmlWriter.writeEndDocument();
        String xmlSend = writeContentLength(xmlWriter);
        try {
            String[] tmpStrRet = sendToBank(xmlSend, p_req1944.reqHeader.transType, p_req1944.reqHeader.commandCode);
            if (tmpStrRet[0].length() == 0) {
                String returnXml = tmpStrRet[1].substring(tmpStrRet[1].indexOf("<FOX>"), tmpStrRet[1].length());
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(returnXml, tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/CODE");
                    String tmpHostStatus = tmpBkReader.getFirstText(
                            "/FOX/SECURITIES_MSGSRSV1/XFERINQTRNRS/XFERINQRS/XFERLIST/XFER/XFERPRCSTS/XFERPRCCODE");
                    if (tmpRetCode.equals("0")) {
                        if (tmpBkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/XFERINQTRNRS/TRNUID")
                                .equals(p_req1944.askNumber)) {
                            tmpRetAtsDetail.respCode = "0";
                            tmpRetAtsDetail.respInfo = "success";
                            tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                        } else {
                            tmpRetAtsDetail.respCode = "-1";
                            tmpRetAtsDetail.respInfo = "请求REQUEST_SN与响应不相符";
                        }
                        tmpRetAtsDetail.transState = tmpHostStatus;
                        tmpRetAtsDetail.payInfoCode = tmpHostStatus;
                        tmpRetAtsDetail.respInfo = tmpBkReader.getFirstText(
                                "/FOX/SECURITIES_MSGSRSV1/XFERINQTRNRS/XFERINQRS/XFERLIST/XFER/XFERPRCSTS/MESSAGE");
                    } else {
                        tmpRetAtsDetail.respCode = "-1";
                        tmpRetAtsDetail.transState = tmpBkReader
                                .getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY");
                        tmpRetAtsDetail.respInfo = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/MESSAGE");
                        tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                        tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                    }
                    if (StringHelper.isNullOrEmpty(tmpRetAtsDetail.reqSeqID)) {
                        tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    /**
     * 3.4.2 查询转账交易状态
     */
    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        RetAtsSingleBat retAts = new RetAtsSingleBat(p_req1944BAT.reqHeader);
        retAts.reqBatchNO = p_req1944BAT.reqBatchNO;
        String tmpRespCode = "";
        String tmpRespInfo = "";
        boolean hasMatched = false;
        try {
            while (p_req1944BAT.readRecord()) {
                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.autoFormat = false;
                writeCommonQryHeaderEn(xmlWriter, "encoding=\"gb2312\"");
                xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
                xmlWriter.writeStartElement(CIB01TransType.Q1908);
                xmlWriter.writeElementString("TRNUID", p_req1944BAT.readedDetail.reqSeqID);

                xmlWriter.writeStartElement("XFERINQRQ");
                xmlWriter.writeElementString("CLIENTREF", p_req1944BAT.readedDetail.reqSeqID);
                //xmlWriter.writeEndElement();


                xmlWriter.writeEndDocument();

                //WriteBankLogStep2(xmlWriter.toXmlString());

                String xmlSend = writeContentLength(xmlWriter);
                String[] tmpStrRet = sendToBank(xmlSend);
                //p_req1944BAT.bankInteractionTime = Long.valueOf(tmpStrRet[2]);
                //WriteBankLogStep3(tmpStrRet[1]);

                if (tmpStrRet[0].length() == 0) {
                    String returnXml = tmpStrRet[1].substring(tmpStrRet[1].indexOf("<FOX>"), tmpStrRet[1].length());

                    //WriteBankLogLn2("银行响应有效数据:\r\n" + returnXml);

                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(returnXml, tmpSbMsg);
                    if (tmpBkReader != null) {
                        tmpRespCode = "0";
                        String returnCode = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/CODE");
                        if (returnCode.equals("0")) {
                            while (tmpBkReader.read("/FOX/SECURITIES_MSGSRSV1/XFERINQTRNRS/XFERINQRS/XFERLIST/XFER")) {
                                retAts.batRespCode = "0";
                                XElement tmpRetNode = tmpBkReader.readedXElement;
                                RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();

                                tmpRetDetail.respCode = "0";
                                tmpRetDetail.respInfo = tmpRetNode.getSingleText("XFERPRCSTS/MESSAGE");
                                tmpRetDetail.reqSeqID = p_req1944BAT.readedDetail.reqSeqID;//tmpRetNode.getSingleText("XFERINFO/CHEQUENUM");
                                tmpRetDetail.transState = tmpRetNode.getSingleText("XFERPRCSTS/XFERPRCCODE");
                                tmpRetDetail.payInfoCode = tmpRetNode.getSingleText("XFERPRCSTS/XFERPRCCODE");
                                tmpRetDetail.transAmt = tmpRetNode.getSingleText("XFERPRCSTS/TRNAMT");

                                retAts.writeRetDetail(tmpRetDetail);
                                hasMatched = true;
                            }
                        } else {
                            tmpRespCode = "-1";
                            tmpRespInfo = tmpBkReader.getFirstText("/FOX/SIGNONMSGSRSV1/SONRS/STATUS/SEVERITY");
                        }
                    } else {
                        tmpRespCode = "-1";
                        tmpRespInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = tmpStrRet[1];
                }
            }
            if (!hasMatched) {
                retAts.batRespCode = tmpRespCode;
                retAts.batRespInfo = tmpRespInfo;
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            retAts.batRespCode = "-1";
            retAts.batRespInfo = ex.getMessage();

            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}
